var gsti;
var currentStories = new Array();
var playing = true;

//getElementById
function $ei(id, parentNode) {
	parentNode = parentNode || document;
	return parentNode.getElementById(id);
}

//getAttribute
function $a(parentNode, att) {
	return parentNode.getAttribute(att);
}

//getElementByTagName
function $et(tagName, parentNode) {
	parentNode = parentNode || document;
	return parentNode.getElementsByTagName(tagName)[0];
}

//getElementByClassName
function $ec(className, parentNode) {
        parentNode = parentNode || document;
        elements = parentNode.getElementsByTagName("*");
        for (i=0; i<elements.length; i++) {
                if (elements[i].hasAttribute('class') && elements[i].getAttribute('class') == className) {
                        return elements[i];
                }
        }
        
}
//Xpath
function $xp(aNode, aExpr) {
	var xpe = new XPathEvaluator();
	var nsResolver = xpe.createNSResolver(aNode.ownerDocument == null ?
	aNode.documentElement : aNode.ownerDocument.documentElement);
	var result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null);
	var found = [];
	var res;
	while (res = result.iterateNext())
		found.push(res);
	return found;
}
String.prototype.escapeEntities = function() {
	return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
}

function fetchData(url, handler) {
	//alert("inside fetchData");
        $ei('diggIndicator').style.display = '';
        $ei("diggIndicator").setAttribute('mode', 'undetermined');
	var request = Components.
              classes["@mozilla.org/xmlextras/xmlhttprequest;1"].
              createInstance();

	// QI the object to nsIDOMEventTarget to set event handlers on it:

	request.QueryInterface(Components.interfaces.nsIDOMEventTarget);
	request.addEventListener("load", handler, false);
        request.addEventListener("error", handleError, false);

	// QI it to nsIXMLHttpRequest to open and send the request:

	request.QueryInterface(Components.interfaces.nsIXMLHttpRequest);
	request.open("GET", url, true);
	request.send(null);
        //$ei('diggIndicator').style.display = '';
        
}

function handleError(e) {
        $ei('storyList').appendItem("!! Error accessing Digg !!");
        //$ei('diggIndicator').style.display = 'none';
}

function populateMenu(e) {
        XHR = e.target;
	//myDump(XHR.responseText);
	data = XHR.responseXML;
        topics = $xp(data, "/topics/topic");
        while ($ei('topicPopup').firstChild) {
                $ei('topicPopup').removeChild($ei('topicPopup').firstChild);
        }
        
        for (i=0; i<topics.length; i++) {
                menu = document.createElement('menu');
                menu.setAttribute('id', $a(topics[i], 'short_name') + 'Menu');
                menu.setAttribute('label', $a(topics[i], 'name'));
                menu.setAttribute('accesskey', $a(topics[i], 'name').substring(0, 1));
                
                menupopup = document.createElement('menupopup');
                menupopup.setAttribute('id', $a(topics[i], 'short_name') + 'Popup');
                
                menuitem = document.createElement('menuitem');
                menuitem.setAttribute('label', 'All');
                menuitem.setAttribute('value', '/topic/' + $a(topics[i], 'short_name') + '/all');
                menuitem.setAttribute('accesskey', 'A');
                menuitem.setAttribute('oncommand', "setEndPoint(this.value)");
                menupopup.appendChild(menuitem);
                
                menuitem = document.createElement('menuitem');
                menuitem.setAttribute('label', 'Popular');
                menuitem.setAttribute('value', '/topic/' + $a(topics[i], 'short_name') + '/popular');
                menuitem.setAttribute('accesskey', 'P');
                menuitem.setAttribute('oncommand', "setEndPoint(this.value)");
                menupopup.appendChild(menuitem);
                
                menuitem = document.createElement('menuitem');
                menuitem.setAttribute('label', 'Upcoming');
                menuitem.setAttribute('value', '/topic/' + $a(topics[i], 'short_name') + '/upcoming');
                menuitem.setAttribute('accesskey', 'U');
                menuitem.setAttribute('oncommand', "setEndPoint(this.value)");
                menupopup.appendChild(menuitem);
                
                menu.appendChild(menupopup);
                
                //alert($a(topics[i], 'name'));
                $ei('topicPopup').appendChild(menu);
        }
        
        containers = $xp(data, "/topics/topic/container");
        while ($ei('containerPopup').firstChild) {
                $ei('containerPopup').removeChild($ei('containerPopup').firstChild);
        }
        
        filteredContainers = {name: [], short_name: []};
        for (i=0; i<containers.length; i++) {
                name = $a(containers[i], 'name');
                short_name = $a(containers[i], 'short_name');
                if (filteredContainers.name.indexOf(name) == -1) {
                        filteredContainers.name.push(name);
                        filteredContainers.short_name.push(short_name);
                }
        }
        //myDump(uneval(filteredContainers));
        
        for (i=0; i<filteredContainers.name.length; i++) {
                menu = document.createElement('menu');
                menu.setAttribute('id', filteredContainers.short_name[i] + 'Menu');
                menu.setAttribute('label', filteredContainers.name[i]);
                menu.setAttribute('accesskey', filteredContainers.name[i].substring(0, 1));
                
                menupopup = document.createElement('menupopup');
                menupopup.setAttribute('id', filteredContainers.short_name[i] + 'Popup');
                
                menuitem = document.createElement('menuitem');
                menuitem.setAttribute('label', 'All');
                menuitem.setAttribute('value', '/container/' + filteredContainers.short_name[i] + '/all');
                menuitem.setAttribute('accesskey', 'A');
                menuitem.setAttribute('oncommand', "setEndPoint(this.value)");
                menupopup.appendChild(menuitem);
                
                menuitem = document.createElement('menuitem');
                menuitem.setAttribute('label', 'Popular');
                menuitem.setAttribute('value', '/container/' + filteredContainers.short_name[i] + '/popular');
                menuitem.setAttribute('accesskey', 'P');
                menuitem.setAttribute('oncommand', "setEndPoint(this.value)");
                menupopup.appendChild(menuitem);
                
                menuitem = document.createElement('menuitem');
                menuitem.setAttribute('label', 'Upcoming');
                menuitem.setAttribute('value', '/container/' + filteredContainers.short_name[i] + '/upcoming');
                menuitem.setAttribute('accesskey', 'U');
                menuitem.setAttribute('oncommand', "setEndPoint(this.value)");
                menupopup.appendChild(menuitem);
                
                menu.appendChild(menupopup);
                
                //alert($a(topics[i], 'name'));
                $ei('containerPopup').appendChild(menu);
        }
        $ei('diggIndicator').style.display = 'none';
}

function populateStoryList(e) {
	//alert("inside populateStoryList");
	XHR = e.target;
	//alert(XHR.responseText);
	data = XHR.responseXML;
	stories = $xp(data, "/stories/story");
	//alert(stories.length);
	//dumpProperties(titles[0]);
        
        //selectedItem = $ei('storyList').selectedItem;
        
        while ($ei('storyList').firstChild) {
                $ei('storyList').removeChild($ei('storyList').firstChild);
        }
                
        
        var newStories = new Array();
	for (i=0; i<stories.length; i++) {
		//alert(stories[i]);
		title = $et('title', stories[i]).textContent;
		id = $a(stories[i], 'id');
                newStories.push(id);
		//alert(title + " " + id);
		listitem = $ei('storyList').appendChild(document.createElement('richlistitem'));
                listitem.id = "story_" + id;
                htmllistitem = listitem.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml","html:div"));
                htmllistitem.innerHTML = $ei('storyTitleFormat').innerHTML;
                storyTitle = listitem.getElementsByAttribute('class', 'storyTitle')[0];
                storyTitle.appendChild(document.createTextNode(title));
                
                htmllistitem.innerHTML += $ei('storyDetailsFormat').innerHTML;
                
                storyNew= listitem.getElementsByAttribute('class', 'storyNew')[0];
                
                if (currentStories.indexOf(id) != -1) {
                        storyNew.style.textDecoration = "line-through";
                        storyNew.style.backgroundColor = "black";
                        storyNew.style.color = "white";
                        storyNew.title = "Old";
                }
        }
        currentStories = newStories;
        //$ei('diggIndicator').style.display = 'none';
        
        //Adaptive update interval code START
        sum = 0;
        weights = [0.4, 0.3, 0.2, 0.1]
        for (i=0; i<4; i++) {
                if ($a(stories[0], 'promote_date') != null)
                        diff = parseInt($a(stories[i], 'promote_date')) - parseInt($a(stories[i+1], 'promote_date'));
                else
                        diff = parseInt($a(stories[i], 'submit_date')) - parseInt($a(stories[i+1], 'submit_date'));
                
                sum += weights[i]*diff;
        }
        updateInterval = Math.round(sum*1000);
        
        var prefs = Components.classes["@mozilla.org/preferences-service;1"].
                getService(Components.interfaces.nsIPrefBranch);
                
        previousUpdateInterval = prefs.getIntPref("extensions.diggsidebar.updateinterval")
        prefs.setIntPref("extensions.diggsidebar.updateinterval", updateInterval);
        
        updateIntervalDecay = prefs.getIntPref("extensions.diggsidebar.updateintervaldecay");

        if (previousUpdateInterval == updateInterval)
                prefs.setIntPref("extensions.diggsidebar.updateintervaldecay", (updateIntervalDecay + 1));
        else
                prefs.setIntPref("extensions.diggsidebar.updateintervaldecay", 0);
        
        window.clearTimeout(gsti);
        
        updateInterval = prefs.getIntPref("extensions.diggsidebar.updateinterval")
        updateIntervalDecay = prefs.getIntPref("extensions.diggsidebar.updateintervaldecay");
        
        timeout = Math.round(updateInterval*(Math.pow(1.5, updateIntervalDecay)));
        gsti = window.setTimeout(getStories, timeout);
        //Adaptive update interval code END
        
        $ei('diggIndicator').style.display = 'none';
        
        //prefs.setIntPref("extensions.diggsidebar.progress", 100);
        //$ei("diggIndicator").setAttribute('mode', 'determined');
        //$ei("diggIndicator").setAttribute('value', 100);
        //psi = window.setInterval(showProgress, Math.round(timeout/100));
        //window.setTimeout("window.clearInterval(psi)", timeout);
        
}

//function showProgress() {
//        var prefs = Components.classes["@mozilla.org/preferences-service;1"].
//                getService(Components.interfaces.nsIPrefBranch);
//        progress = prefs.getIntPref("extensions.diggsidebar.progress");
//        prefs.setIntPref("extensions.diggsidebar.progress", (progress - 1));
//        
//        $ei("diggIndicator").setAttribute('value', (parseInt($ei("diggIndicator").getAttribute('value')) - 1));
//}
        
function populateDescription(e) {
	XHR = e.target;
	myDump(XHR.responseText);
	data = XHR.responseXML;
	story = $xp(data, "/stories/story")[0];
	//alert(story);
        now = new Date();
        if ($a(story, 'promote_date') != null)
                then = new Date(parseInt($a(story, 'promote_date').escapeEntities())*1000);
        else
                then = new Date(parseInt($a(story, 'submit_date').escapeEntities())*1000);
        diff = now - then;
        if (diff < 0) diff = 0;
               
        hr = Math.floor(diff/(1000*3600));
        min = Math.floor(diff/(1000*60)) - 60*hr;
        
        listitems = document.getElementsByTagName('richlistitem');
        for (i=0; i<listitems.length; i++) {
                listitems[i].getElementsByAttribute('class', 'storyDetails')[0].style.display = 'none';
                listitems[i].getElementsByAttribute('class', 'storyCEIcon')[0].src = "chrome://diggsidebar/content/image/up.jpg";
        }
        
        storyListItem = $ei('story_'+ $a(story, 'id'))
        storyDetails = storyListItem.getElementsByAttribute('class', 'storyDetails')[0];
        storyDate = storyListItem.getElementsByAttribute('class', 'storyDate')[0];
        storyStatus = storyListItem.getElementsByAttribute('class', 'storyStatus')[0];
        storyContainer = storyListItem.getElementsByAttribute('class', 'storyContainer')[0];
        storyTopic = storyListItem.getElementsByAttribute('class', 'storyTopic')[0];
        storyUserName = storyListItem.getElementsByAttribute('class', 'storyUserName')[0];
        storyDiggs = storyListItem.getElementsByAttribute('class', 'storyDiggs')[0];
        storyComments = storyListItem.getElementsByAttribute('class', 'storyComments')[0];
        storyDesc = storyListItem.getElementsByAttribute('class', 'storyDesc')[0];
        storyLink = storyListItem.getElementsByAttribute('class', 'storyLink')[0];
        storyHref = storyListItem.getElementsByAttribute('class', 'storyHref')[0];
        
        storyCEIcon = storyListItem.getElementsByAttribute('class', 'storyCEIcon')[0];
        storyRead = storyListItem.getElementsByAttribute('class', 'storyRead')[0];
                
	storyDate.innerHTML = ((hr > 0) && (min > 0)) ?
                                                (hr + " hr " + min + " mins ago") :
                                                ((hr == 0) && (min > 0)) ?
                                                (min + " mins ago") :
                                                ((hr == 0) && (min == 0)) ?
                                                "just now" : "";
	storyStatus.innerHTML = $a(story, 'status').escapeEntities();
	//alert($a($et('container', story), 'name').escapeEntities());
	storyContainer.innerHTML = $a($et('container', story), 'name').escapeEntities();
	storyTopic.innerHTML = $a($et('topic', story), 'name').escapeEntities();
	storyUserName.href = "http://digg.com/users/" + $a($et('user', story), 'name').escapeEntities();
	storyUserName.innerHTML = $a($et('user', story), 'name').escapeEntities();
	storyDiggs.innerHTML = $a(story, 'diggs').escapeEntities();
	storyComments.innerHTML = $a(story, 'comments').escapeEntities();
	storyDesc.innerHTML = $et('description', story).textContent.escapeEntities();
	storyLink.href = $a(story, 'link');
	storyHref.href = $a(story, 'href');
        
        storyCEIcon.src = "chrome://diggsidebar/content/image/down.jpg";
        storyRead.style.textDecoration = "line-through";
        storyRead.style.backgroundColor = "black";
        storyRead.style.color = "white";
        storyRead.title = "Read";
        storyNew.style.textDecoration = "line-through";
        storyNew.style.backgroundColor = "black";
        storyNew.style.color = "white";
        storyNew.title = "Old";
        
	storyDetails.style.display = 'block';
        
        $ei('diggIndicator').style.display = 'none';
}

function getStories() {
	//alert("inside getStories");
        var prefs = Components.classes["@mozilla.org/preferences-service;1"].
                getService(Components.interfaces.nsIPrefBranch);
        ep = prefs.getCharPref("extensions.diggsidebar.endpoint") || '';
        //alert(ep);
        $ei('diggEndPoint').value = "digg" + ep;
        
        //ep ='';
	fetchData("http://services.digg.com/stories" + ep.replace(/\/all/g, '') + "?count=30" +
		"&appkey=" + encodeURIComponent("http://diggsidebar.googlepages.com"),
		populateStoryList);
        //gsti = window.setTimeout(getStories, prefs.getIntPref("extensions.diggsidebar.updateinterval"));
}

function getDescription(storyId) {
        myDump(storyId);
        if (storyId == null) return;
	fetchData("http://services.digg.com/story/" + storyId +
		"?appkey=" + encodeURIComponent("http://diggsidebar.googlepages.com"),
		populateDescription);
}

function createMenu() {
        fetchData("http://services.digg.com/topics" +
		"?appkey=" + encodeURIComponent("http://diggsidebar.googlepages.com"),
                populateMenu);
}

function openInTab(href) {
        var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                   .getInterface(Components.interfaces.nsIWebNavigation)
                   .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
                   .rootTreeItem
                   .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                   .getInterface(Components.interfaces.nsIDOMWindow);
        mainWindow.getBrowser().selectedTab = mainWindow.getBrowser().addTab(href);
}

function setEndPoint(ep) {
        var prefs = Components.classes["@mozilla.org/preferences-service;1"].
                getService(Components.interfaces.nsIPrefBranch);
        prefs.setCharPref("extensions.diggsidebar.endpoint", ep);
        window.clearTimeout(gsti);
        //window.clearInterval(psi);
        getStories();
}

function togglePlayPause() {
        if (playing) {
               window.clearTimeout(gsti);
               //window.clearInterval(psi);
               $ei('diggPlayPause').image = "chrome://diggsidebar/content/image/Play.png";
               $ei('diggPlayPause').setAttribute("tooltiptext", "Click to Start autoupdate");
               playing = false;
        } else {
                var prefs = Components.classes["@mozilla.org/preferences-service;1"].
                        getService(Components.interfaces.nsIPrefBranch);
                updateInterval = prefs.getIntPref("extensions.diggsidebar.updateinterval")
                updateIntervalDecay = prefs.getIntPref("extensions.diggsidebar.updateintervaldecay");
        
                timeout = Math.round(updateInterval*(Math.pow(1.5, updateIntervalDecay)));
                //newTimeout = Math.round(timeout*parseInt($ei("diggIndicator").getAttribute('value'))/100);
                gsti = window.setTimeout(getStories, timeout);
                //psi = window.setInterval(showProgress, Math.round(timeout/100));
                //window.setTimeout("window.clearInterval(psi)", newTimeout);
                $ei('diggPlayPause').image = "chrome://diggsidebar/content/image/Pause.png";
                $ei('diggPlayPause').setAttribute("tooltiptext", "Click to Pause autoupdate");
                playing = true;
        }
}


function myDump(aMessage) {
  var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
                                 .getService(Components.interfaces.nsIConsoleService);
  consoleService.logStringMessage("Diggsidebar: " + aMessage);
}


/*TODO
 preferences
 toolbar button
 refresh button
 */
/*DONE
 v0.2
 added kdb navigation
 Added progressmeter
 added error notification
 added accesskeys
 added new story notification
 
 v0.2.1
 adaptive polling interval
 promote_date
 pause/play
 
 v0.5
 new ui
*/